package test.movies;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;

import static org.openqa.selenium.support.PageFactory.initElements;
import static org.openqa.selenium.support.ui.ExpectedConditions.*;

public class MainPage extends PageMovies {
	

    // Logger variable
    private static final org.apache.log4j.Logger LOGGER = org.apache.log4j.Logger.getLogger(MainPage.class);
   

    //Element on Main Page
    private String home ="//a[contains(text(),'Home')]";

    //Element on Main Page
    private String link_to_new_movie ="//img[@title='Add movie']";

    //Field for film searching on Main Page
    private String fieldSearch ="//input[@id='q']";

    // Button LogOut on Main page
    private String buttonLogout =  "//a[contains(text(),'Log out')]";



    /**
     * Constructor of the MainPage class
     * @param driver - configured driver
     */
    public MainPage(WebDriver driver) {
        super(driver);
        initElements(driver, this);
    }


    /**
     * Check if it is the right page
     * @return true if right page
     */
    public boolean checkIfMainPageIsOpen() {

        LOGGER.info("Checking whether the user on the Main Page");
        try{

            WebElement check= new WebDriverWait(driver,20).until(visibilityOfElementLocated(By.xpath(home)));
            LOGGER.info("Main Page is open");

            return true;
        }
        catch (NullPointerException e){
            LOGGER.error("Main Page is disable");
            return false;}

        catch (TimeoutException e){

            LOGGER.error("User currently not on the Main Page!!! Check Login and Password, availability of application!!!");
            return false;}

    }

    // this method open the page for adding of new description
    public AddDescription openNewDescriptionPage() {

        LOGGER.info("Open New Movie Page");

        try{

            WebElement list= new WebDriverWait(driver,20).until(elementToBeClickable(By.xpath(link_to_new_movie)));
            LOGGER.info("Link to addition of new movie is found");

            list.click();

            return new AddDescription(driver);
        }
        catch (NullPointerException e){
            LOGGER.error("Main Page is disable!!!");
            return null;}
        catch (TimeoutException e){
            LOGGER.error("Link to addition of new movie is not found!!!");
            return null;}


    }
    /**
     * This method inserts data of film in the field of Searching and start searching
     * @param filmData
     * @return
     */


    public boolean searchDescription(String filmData) {

        LOGGER.info("Start searching of film");

        try{

            WebElement search= new WebDriverWait(driver,20).until(elementToBeClickable(By.xpath(fieldSearch)));
            LOGGER.info("Insert film name");
            search.sendKeys(Keys.CONTROL + "a");
            search.sendKeys(Keys.DELETE);
            search.sendKeys(filmData);

            LOGGER.info("Start searching");
            search.sendKeys(Keys.RETURN);

            return true;
        }
        catch (NullPointerException e){
            LOGGER.error("Main Page is disable!!!");
            return false;}

        catch (TimeoutException e){

            LOGGER.error("Field for searching is not found!!!!");
            return false;}


    }

    /**
     * This method check if any film with corresponding data is found
     * @param filmData
     * @return
     */
    public boolean checkPresence(String filmData) {

        LOGGER.info("check if Description is found");

        try{
       // List<WebElement> listOfFilms = driver.findElements(By.xpath("//div[@title='" + filmData + "']"));

        List<WebElement> listOfFilms = new WebDriverWait(driver,10).until(visibilityOfAllElementsLocatedBy(By.xpath("//div[@title='" + filmData + "']")));

        int numberOfFilms = listOfFilms.size();

        if (numberOfFilms!= 0) {

            if (numberOfFilms > 1) {
                LOGGER.info("The number of found Descriptions is " + numberOfFilms);
                return true;}
            else {LOGGER.info("Only one Description contains such name");
                return true;}
        }


        else {LOGGER.info("Description which contains the word " + filmData +" is not found");
            return false;}
        }
        catch (NullPointerException e) {
            LOGGER.error("Main Page is disable!!!!");
            return false;
        }
        catch (TimeoutException e) {
            LOGGER.info("Description which contains the word " + filmData +" is not found");
            return false;
        }

    }

    // this method checks if film is present
    public boolean descriptionIsPresent(String filmData){

        LOGGER.info("check if Description is present");

        try{
            WebElement film = new WebDriverWait(driver,10).until(visibilityOfElementLocated(By.xpath("//div[@title='" + filmData + "']")));
            LOGGER.info("Description is present");
            return true;
        }
        catch (NullPointerException e) {
            LOGGER.error("Main Page is disable!!!!");
            return false;
        }
        catch (TimeoutException e) {
            LOGGER.info("Description which contains the word " + filmData +" is not found");
            return false;
        }

    }

    // this method checks if Description is present and remember it
    public WebElement rememberItem(String filmData){

        LOGGER.info("check if item is present and remember it");

        try{
            WebElement film = new WebDriverWait(driver,10).until(visibilityOfElementLocated(By.xpath("//div[@title='" + filmData + "']")));
            LOGGER.info("Item is present");
            return film;
        }
        catch (NullPointerException e) {
            LOGGER.error("Main Page is disable!!!!");
            return null;
        }
        catch (TimeoutException e) {
            LOGGER.info("Item " + filmData +" is not found");
            return null;
        }

    }

    // this method wait until Searching finishes
    public boolean waitUntilSearchFinish(WebElement filmData){

        LOGGER.info("Wait until Search process finishes");

        try{
            WebDriverWait waitSearch = new WebDriverWait(driver,10);
            waitSearch.until(ExpectedConditions.stalenessOf(filmData));

            LOGGER.info("Search finished");
            return true;
        }
        catch (NullPointerException e) {
            LOGGER.error("Main Page is disable!!!!");
            return false;
        }
        catch (TimeoutException e) {
            LOGGER.info("Search doesn't work!!");
            return false;
        }

    }

    // this method open info of film
    public MovieInfo openMovieInfo (String filmData)

    {
        LOGGER.info("Select film and open his details");

        try{

            WebElement selectFilm = new WebDriverWait(driver,20).until(elementToBeClickable(By.xpath("//div[@title='" + filmData + "']")));
            LOGGER.info(" Open Movie info");
            selectFilm.click();


            return new MovieInfo (driver);
        }
        catch (NullPointerException e){
            LOGGER.error("Main Page is disable!!!");
            return null;}

        catch (TimeoutException e){

            LOGGER.error("Film is not found!!!!");
            return null;}

    }

    // method switches to Confirmation PopUp and click Ok
        public boolean confirmAction(){
        try {
            WebDriverWait wait = new WebDriverWait(driver, 20);
            wait.until(alertIsPresent()).accept();
            //LOGGER.info("Confirm PopUp is available");
            LOGGER.info("Confirm Action");
            return true;
        } catch (NoAlertPresentException e) {
            return false;
        }
        catch (TimeoutException e) {
            return false;
        }
    }

    // this method log out from application
    public LoginPage logOut() {
        try{

            WebElement back = new WebDriverWait(driver,20).until(elementToBeClickable(By.xpath(buttonLogout)));
            LOGGER.info("Log out");
            back.click();
            LOGGER.info("Look at PopUp");
            confirmAction();


            return new LoginPage (driver);
        }
        catch (NullPointerException e){
            LOGGER.error("Main Page is disable!!!");
            return null;}

        catch (TimeoutException e){

            LOGGER.error("Button for log out is not found!!!!");
            return null;}

    }

    // this method creates new description with checking of mandatory fields and result of creation
    public boolean createNewDescription(String titleFilm, String yearFilm){

        LOGGER.info("Create New Description");
       try {
           // open Add New Description Page
           AddDescription page = openNewDescriptionPage();
           Assert.assertNotNull(page, "Link for adding og New Description is not found!!!!");

           // check if New Description Page is open
           boolean checkNewDescriptionPage = page.checkIfNewDescriptionIsOpen();
           Assert.assertTrue(checkNewDescriptionPage,"New Description Page List is not opened!!!!");

           // insert data in mandatory fields of Description
           boolean fillInFields = page.insertMovieData(titleFilm, yearFilm);
           Assert.assertTrue(fillInFields,"One of the fields is not found!!!!");

           // check if all mandatory fields are filled
           boolean mandatoryFields = page.checkIfRequiredDataIsSet();
           Assert.assertTrue(mandatoryFields,"At least one mandatory fields is not set!!!");

           // save new description
           MovieInfo info = page.createNewDescription();
           Assert.assertNotNull(info,"Button for saving is not found!!!");

           // check if movie info of new description is open
           boolean checkCreation = info.checkIfMovieInfoIsOpen();
           Assert.assertTrue(checkCreation,"New description is not added!!!");

           // check if Movie Info is correct
           boolean checkInfo = info.checkMovieInfo(titleFilm, yearFilm);
           Assert.assertTrue(checkInfo,"Wrong Description is displayed!!!");
           
           return true;

       } catch (NullPointerException e){
           LOGGER.error("Application is disable!!! Error: " + e.toString());
           return false;
           }
       catch (TimeoutException e){
           LOGGER.error("Error with creation of New Description!!!!" + e.toString());
          return false;
       }

    }
    

    // this method opens new description, enters invalid data and checks that warning about this data is displayed
    public boolean addNewDescription_Fail(String titleFilm, String yearFilm) {

        LOGGER.info("Create New Description");
        try {
            // open Add New Description Page
            AddDescription page = openNewDescriptionPage();
            Assert.assertNotNull(page, "Link for adding og New Description is not found!!!!");

            // check if New Description Page is open
            boolean checkNewDescriptionPage = page.checkIfNewDescriptionIsOpen();
            Assert.assertTrue(checkNewDescriptionPage, "New Description Page List is not opened!!!!");

            // insert data in mandatory fields of Description
            boolean fillInFields = page.insertMovieData(titleFilm, yearFilm);
            Assert.assertTrue(fillInFields, "One of the fields is not found!!!!");

            // check if all mandatory fields are filled
            boolean mandatoryFields = page.checkIfRequiredDataIsSet();
            Assert.assertFalse(mandatoryFields,"Warning about not filled mandatory fields is not set!!!");

            return true;

        } catch (NullPointerException e) {
            LOGGER.error("Application is disable!!!");
            return false;
        } catch (TimeoutException e) {
            LOGGER.error("Error with creation of New Description!!!!" + e.toString());
            return false;
        }
    }

    // this method searches description
    public boolean doSearchDescription(String titleFilm,String basicFilm){

        LOGGER.info("Search Description");
        try {

            // check if basic description exists
            WebElement checkBasic = rememberItem(basicFilm);
            Assert.assertNotNull(checkBasic, "Basic Description is not found !!!!");

            // insert description and start its searching
            boolean search = searchDescription(titleFilm);
            Assert.assertTrue(search,"Field for searching is not found!!!!");

            // check if search process works
            boolean checkSearch = waitUntilSearchFinish(checkBasic);
            Assert.assertTrue(checkSearch,"Searching doesn't work!!!!");

            return  true;

        } catch (NullPointerException e){
            LOGGER.error("Application is disable!!!" + e.toString());
            return false;}
        catch (TimeoutException e){
            LOGGER.error("Error with searching of escription!!!!" + e.toString());
            return false;
        }

    }

    // this method removes description
    public boolean removeDescription(String titleFilm){

        LOGGER.info("Remove Description");
        try {

            // open info of film
            MovieInfo info = openMovieInfo(titleFilm);
            Assert.assertNotNull(info,"Description is not found!!!");

            // check if movie info is open
            boolean checkIfoPage = info.checkIfMovieInfoIsOpen();
            Assert.assertTrue(checkIfoPage, "Film description is not open!!!");

            // remove description
            MainPage delete = info.removeDescription();
            Assert.assertNotNull(delete, "Film description is not remove!!!");

            //check if Main Page is return
            boolean returnMainPage = checkIfMainPageIsOpen();
            Assert.assertTrue(returnMainPage,"Main Page is not returned!!!!");

            // check if description is deleted
            boolean checkPresence = descriptionIsPresent(titleFilm);
            Assert.assertFalse(checkPresence,"Description is still present !!!!");

            return  true;

        } catch (NullPointerException e){
            LOGGER.error("Application is disable!!!");
            return false;}
        catch (TimeoutException e){
            LOGGER.error("Error with removing of escription!!!!" +e.toString());
            return false;
        }

    }

    
    
    
    
}